﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace ServerFrame
{
    public class Mytoken
    {
        public delegate void SendDE(SocketAsyncEventArgs e);//发送完成事件委托
        public delegate void Close_DE(Mytoken token, string error);//写操作失败时关闭token
        public SendDE send_de;
        public Close_DE close_de;
        public SocketAsyncEventArgs args_write, args_read; //异步读写操作
        public Socket socket;
        public AbsMessageCenter center;
        List<byte> cache=new List<byte>(); //缓存区
        Queue<TransModel> wqueue=new Queue<TransModel>();//模型队列
        bool reading = false;//读取状态
        bool writing = false;//写入状态
        public Mytoken()
        {
            args_read = new SocketAsyncEventArgs();
            args_write = new SocketAsyncEventArgs();
            args_read.UserToken = this;
            args_write.UserToken = this;
            args_read.SetBuffer(new byte[1024], 0, 1024);//初始化读取异步缓冲区，不然会报空指针错误
        }
        public void Close()
        {
            try {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
                socket = null;
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
        /// <summary>
        /// 接受数据
        /// </summary>
        /// <param name="data">接受到的数据</param>
        public void Receive(byte[] data)
        {
            cache.AddRange(data);
            if (!reading)
            {
                reading = true;
                read();
            }

        }
        /// <summary>
        /// 读取并处理缓存区cache中的数据
        /// </summary>
        public void read()
        {
            byte[] result = Lengthcode.LengthDeCode(ref cache);
            if (result == null)
            {
                reading = false;
                return;
            }
            //传输模型解码
            else
            {
                TransModel model = TransModelCode.TransModelDeCode(result);
                if (model == null)
                {
                    reading = false;
                    return;
                }
                //通知上层应用有消息到达，准备处理model
                center.OnMessageRecive(this,model);
                read();//进行递归，继续读取消息
            }
        }
        /// <summary>
        /// 发送模型
        /// </summary>
        public void send(TransModel model)
        {
            wqueue.Enqueue(model);
            if (!writing)
            {
                writing = true;
                write();
            }
        }
        public void write()
        {
            if (wqueue.Count <= 0)
            {
                writing = false;
                return;
            }
            TransModel model = wqueue.Dequeue();
            byte[] result = TransModelCode.TransModelECode(model);//传输模型编码
            if (result == null || result.Length <= 0)
            {
                writing = false;
                return;
            }
            byte[] re = Lengthcode.LengthECode(result);//长度编码
            args_write.SetBuffer(re, 0, re.Length);//设置写入异步套接字的缓冲区
            try
            {
                bool v = socket.SendAsync(args_write);//判断是否挂起
                if (!v)
                {
                    send_de(args_write);
                }
            }
            catch (Exception ex)
            {
                close_de(this, "发送数据失败");
                Console.WriteLine(ex.ToString());
            }
        }
    }
}
